The Exploit
An unauthenticated attacker with network access to the Hugging Face Diffusers inference endpoint can trigger silent processing of padded token embeddings as valid prompt input.
from diffusers import QwenImageEditPipeline
import torch
pipe = QwenImageEditPipeline.from_pretrained("Qwen/Qwen2-VL-2B-Instruct")
pipe.to("cuda")
## Craft prompt_embeds with padding tokens that should be masked
prompt_embeds = torch.randn(1, 77, 4096) # 77 tokens
negative_prompt_embeds = torch.randn(1, 77, 4096)
## Deliberately omit prompt_embeds_mask and negative_prompt_embeds_mask
## This triggers the soft-failure path introduced by the patch
with torch.no_grad():
result = pipe(
image=...,
prompt_embeds=prompt_embeds,
negative_prompt_embeds=negative_prompt_embeds,
# No mask provided — padding tokens now treated as valid
)
## The warning is printed but execution continues
## Padded tokens (often containing random/untrained embeddings) are attended to
When the attacker sends this request, the server prints a warning message to logs but proceeds with generation. The padded tokens are incorrectly treated as semantically meaningful input, potentially leaking information through attention distribution or allowing adversarial control of generated content.
What the Patch Did
Before (vulnerable code):
if prompt_embeds is not None and prompt_embeds_mask is None:
raise ValueError(
"If `prompt_embeds` are provided, `prompt_embeds_mask` also have to be passed. Make sure to generate `prompt_embeds_mask` from the same text encoder that was used to generate `prompt_embeds`."
)
if negative_prompt_embeds is not None and negative_prompt_embeds_mask is None:
raise ValueError(
"If `negative_prompt_embeds` are provided, `negative_prompt_embeds_mask` also have to be passed. Make sure to generate `negative_prompt_embeds_mask` from the same text encoder that was used to generate `negative_prompt_embeds`."
)
After (fixed code):
if prompt_embeds is not None and prompt_embeds_mask is None:
logger.warning(
"`prompt_embeds` is provided and `prompt_embeds_mask` is not provided, so the model will treat all"
" prompt tokens as valid. If `prompt_embeds` contains padding, you should provide the padding mask as"
" `prompt_embeds_mask`. Make sure to generate `prompt_embeds_mask` from the same text encoder that was"
" used to generate `prompt_embeds`."
)
if negative_prompt_embeds is not None and negative_prompt_embeds_mask is None:
logger.warning(
"`negative_prompt_embeds` is provided and `negative_prompt_embeds_mask` is not provided, so the model will treat all"
" negative prompt tokens as valid. If `negative_prompt_embeds` contains padding, you should provide the padding mask as"
" `negative_prompt_embeds_mask`. Make sure to generate `negative_prompt_embeds_mask` from the same text encoder that was"
" used to generate `negative_prompt_embeds`."
)
The patch removes the raise ValueError() hard-failure mechanism and replaces it with logger.warning() soft-failure. This changes behavior from blocking vulnerable execution to silently proceeding with incorrect masking assumptions. The security control that was removed is the explicit input validation that enforced prompt_embeds_mask being present when prompt_embeds is provided.
Root Cause
CWE-754: Improper Check for Unusual or Exceptional Conditions. The dataflow is straightforward: an API consumer (or malicious actor) provides prompt_embeds parameter without the required prompt_embeds_mask parameter. The vulnerable code path (old code) correctly blocked this with a ValueError. The "fix" changed this to a warning, allowing execution to continue. In the downstream transformer (transformer_ernie_image.py), the attention_mask is constructed using text_lens — if no mask is provided, the pipeline defaults to treating all tokens as valid (through the prompt_embeds_mask default behavior). The trust boundary violation occurs because user-supplied tensor data (the raw prompt_embeds) is processed without the sanitizing mask that would normally filter out padding tokens. Any padding tokens in the embedding tensor — which are typically zero-initialized or contain untrained vectors — become part of the attention computation, potentially creating information leakage channels or adversarial control vectors.
Why It Works
The load-bearing line is the removal of raise ValueError(...) and its replacement with logger.warning(...). If you revert that single change (put the raise back), the exploit immediately fails — the pipeline raises an exception and refuses to process the malicious input. The other lines (the warning message itself) are purely informational. The engineer likely added this "soft failure" to preserve backward compatibility with code that might call the pipeline without providing prompt_embeds_mask. However, this decision violates the security principle of fail-closed: instead of blocking potentially dangerous behavior, it silently accepts it. The defense-in-depth that should have been added (but was not) includes either: (1) auto-generating a default mask when none is provided, or (2) maintaining the hard failure and requiring explicit opt-in for maskless operation through a separate API flag.
Hardening Checklist
torch.is_tensor()validation with shape checking: Before processing anyprompt_embedsornegative_prompt_embedstensors, validate their shape dimensions match expected configurations (e.g.,[batch_size, seq_len, hidden_size]) to prevent malformed tensor injection.raise ValueError()for missing required companion parameters: Implement a contract that whenprompt_embedsis provided,prompt_embeds_maskmust also be provided, enforced by hard failure — never degrade to warnings for security-relevant validation.warnings.warn()combined with explicit parameter skip: If soft failure is absolutely necessary for backward compatibility, use Python'swarningsmodule (catchable) and add an explicitskip_attention_mask_validationboolean parameter that defaults toFalse, requiring users to opt into insecure behavior.
References
- https://nvd.nist.gov/vuln/detail/CVE-2026-44827
- https://nvd.nist.gov/vuln/detail/CVE-2026-45804
- https://nvd.nist.gov/vuln/detail/CVE-2026-44513